/**
 * Created by chengke on 2018/2/9.
 */

let iconv = require('iconv-lite');
let FutuHttpClient = require('@futu/httpclient');
let FutuHttpRequest = FutuHttpClient.FutuHttpRequest;
let KeywordReportDay = require('../models/KeywordReportDay');

module.exports = ReportService;

const BASE_API_URL = 'https://api.baidu.com/json/sms/service/ReportService/';
const API_REPORT_ID = 'getProfessionalReportId';
const API_REPORT_STATE = 'getReportState';
const API_REPORT_FILE = 'getReportFileUrl';

const KEYWORD_REPORT_ATTRS = [
    'date',
    'accountId',
    'accountName',
    'planId',
    'planName',
    'unitId',
    'unitName',
    'keywordId',
    // 'wordId',
    'keyword',
    'impression',
    'click',
    'cost',
    'ctr',
    'cpc',
    'cpm',
    'position'
];

/**
 * ReportService
 *
 * @constructor
 * @param {String} username 用户名
 * @param {String} password 密码
 * @param {String} token API 令牌
 * @param {Object} options 扩展参数
 */
function ReportService(username, password, token, options = {}) {
    this.username = username;
    this.password = password;
    this.token = token;
    this.options = options;
    this.commonHeader = {
        'username': this.username,
        'password': this.password,
        'token': this.token
    };
}

ReportService.prototype.getKeywordDayReport = async function (startDate, endDate) {
    // 1. 获取 reportId
    let reportId = await this.getKeywordReportId(startDate, endDate);
    console.log('reportState is: ' + reportId);
    // 2. 获取 报告生成状态
    let reportState = await this.getReportState(reportId);
    console.log('reportState is: ' + reportState);
    // 3. 获取 报告下载路径
    return await this.getReportFile(reportId, reportState);
};

/**
 * 获取关键词日报
 * @param {String} startDate 开始时间
 * @param {String} endDate 结束时间
 * @return {String} reportId
 */
ReportService.prototype.getKeywordReportId = async function (startDate, endDate) {
    let result = await this._requestSemAPI(BASE_API_URL + API_REPORT_ID, {
        'reportRequestType': {
            'performanceData' : ['cost', 'cpc', 'click', 'impression', 'ctr', 'cpm', 'position'],
            'startDate' : startDate,
            'endDate' : endDate,
            'reportType': 9,
            'levelOfDetails': 6,
            'format': 2
        }

    });
    console.log(JSON.stringify(result, null, 2));
    if (result.header && result.header.status === 0) {
        return result.body.data[0].reportId;
    } else {
        return '';
    }
};

ReportService.prototype.getReportState = async function (reportId) {
    let result = await this._requestSemAPI(BASE_API_URL + API_REPORT_STATE, { 'reportId': reportId});
    console.log(JSON.stringify(result, null, 2));
    if (result.header && result.header.status === 0) {
        return result.body.data[0].isGenerated;
    } else {
        return '';
    }
};

ReportService.prototype.getReportFile = async function (reportId, reportState) {
    if (reportState === 3) {
        let result = await this._requestSemAPI(BASE_API_URL + API_REPORT_FILE, { 'reportId': reportId});
        console.log(JSON.stringify(result, null, 2));
        if (result.header && result.header.status === 0) {
            return result.body.data[0].reportFilePath;
        }
    } else {
        await ReportService.timeout(1000);
        reportState = await this.getReportState(reportId);
        console.log('[IN getReportFile], reportState = ' + reportState);
        return await this.getReportFile(reportId, reportState);
    }

};

ReportService.prototype._requestSemAPI = async function (url, body) {
    let client = await FutuHttpClient.getInstanceByEndpoint();
    let request = new FutuHttpRequest(url, {}, {});
    request.setIsJson(true);
    request.setData({
        'header': this.commonHeader,
        'body': body
    });
    let response = await client.request('post', request);
    if (response.httpStatusCode !== 200) {
        throw new Error('request ' + url + 'failed: ' + response.message);
    }
    return JSON.parse(response.data || '{}');
};

ReportService.prototype.syncReportData = async function (url) {
    let client = await FutuHttpClient.getInstanceByEndpoint();
    let request = new FutuHttpRequest(url, {}, {});
    let response = await client.request('get', request, {encoding:null});
    if (response.httpStatusCode !== 200) {
        throw new Error('request ' + url + 'failed: ' + response.message);
    }
    // console.log(response.data);
    let data = iconv.decode(response.data, 'GB2312');
    let rows = data.split('\n');
    rows = rows.slice(1, rows.length);
    console.log(rows.length);
    let items = rows.map(function (item) {
        let attrs = item.split('\t');
        let report = {};
        for (let i = 0; i < attrs.length; i++) {
            report[KEYWORD_REPORT_ATTRS[i]] = attrs[i];
        }
        console.log(report);
        return report;
    });
    let result = await KeywordReportDay.bulkCreate(items);
    console.log(result);
};

ReportService.timeout = function (ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
};
